<template>
  <el-upload
    class="image-upload border border-dashed border-el-light rounded cursor-pointer overflow-hidden"
    :show-file-list="false"
    :on-success="onSuccess"
    :http-request="onHttpRequest"
  >
    <img v-if="image" :src="image" class="w-30 h-30 align-bottom" />
    <el-icon v-else class="w-30! h-30!">
      <EpPlus class="color-gray text-lg" />
    </el-icon>
  </el-upload>
</template>

<script setup lang="ts">
import { EpPlus } from '@/assets/icons'
import type { UploadProgressEvent, UploadProps, UploadRequestOptions } from 'element-plus'
import http from '@/http'
import type { AxiosRequestConfig, AxiosProgressEvent, AxiosError } from 'axios'
import { UploadAjaxError } from 'element-plus/es/components/upload/src/ajax.mjs'

interface Props {
  imageModel?: string
}

const props = defineProps<Props>()

const image = ref<string | undefined>()
const imageId = defineModel<number>()

const formModel = inject<Record<string, any>>('formModel')

if (props?.imageModel && formModel && props.imageModel in formModel) {
  image.value = formModel[props.imageModel]
}

// 自定义 Ajax
const onHttpRequest = async (options: UploadRequestOptions) => {
  const config: AxiosRequestConfig = {
    url: options.action,
    method: options.method,
    headers: options.headers instanceof Headers ? {} : options.headers,
    withCredentials: options.withCredentials,
    onUploadProgress(evt: AxiosProgressEvent) {
      const progressEvt: UploadProgressEvent = evt.event
      progressEvt.percent = evt.progress || 0
      options.onProgress(progressEvt)
    }
  }
  const formData = new FormData()
  if (options.data) {
    for (const [key, value] of Object.entries(options.data)) {
      if (Array.isArray(value)) {
        value.forEach((v) => formData.append(`${key}[]`, v))
      } else {
        formData.append(key, value)
      }
    }
  }
  formData.append(options.filename, options.file, options.file.name)

  const headers: Record<string, string> = {}
  if (options.headers instanceof Headers) {
    options.headers.forEach((value, key) => (headers[key] = value))
  } else {
    for (const [key, value] of Object.entries(headers)) {
      if (!value) continue
      headers[key] = String(value)
    }
  }
  // config.headers = {
  //   ...headers,
  //   'Content-Type': 'multipart/form-data'
  // }
  config.headers = headers
  config.data = formData

  return http
    .request(config)
    .catch((data) => {
      options.onSuccess(data)
    })
    .catch((e: AxiosError) => {
      options.onError(
        new UploadAjaxError(e.message, e.response?.status || 500, options.method, options.action)
      )
    })
}

const removeImages: string[] = []
const onSuccess: UploadProps['onSuccess'] = async (response) => {
  if (response.status) {
    if (image.value) {
      removeImages.push(image.value)
    }
    imageId.value = response.data.id
    image.value = response.data.path
  }
}

defineExpose({
  deleteImage: () => {
    return removeImages.slice()
  }
})
</script>

<style scoped lang="scss">
.image-upload {
  :deep(.el-upload) {
    vertical-align: bottom;
  }
}
</style>
